package repository

import (
	"fmt"

	"github.com/yourusername/rss-reader-ai/internal/model"
	"gorm.io/gorm"
)

// =====================================================
// TagRepository 接口定义
// =====================================================

// TagRepository 标签数据访问接口
type TagRepository interface {
	// Create 创建标签
	Create(tag *model.Tag) error

	// GetByID 根据ID获取标签
	GetByID(id int64) (*model.Tag, error)

	// GetByName 根据名称获取标签
	GetByName(name string) (*model.Tag, error)

	// GetOrCreate 获取或创建标签(如果不存在则创建)
	GetOrCreate(name string) (*model.Tag, error)

	// List 获取所有标签
	List() ([]*model.Tag, error)

	// ListByArticle 获取文章的所有标签
	ListByArticle(articleID int64) ([]*model.Tag, error)

	// Update 更新标签
	Update(tag *model.Tag) error

	// Delete 删除标签
	Delete(id int64) error

	// AddToArticle 为文章添加标签
	AddToArticle(articleID int64, tagID int64) error

	// RemoveFromArticle 从文章移除标签
	RemoveFromArticle(articleID int64, tagID int64) error

	// SyncArticleTags 同步文章的标签(先删除旧标签,再添加新标签)
	SyncArticleTags(articleID int64, tagNames []string) error

	// Count 统计标签数量
	Count() (int64, error)
}

// =====================================================
// TagRepository 接口实现
// =====================================================

// tagRepository 标签数据访问实现
type tagRepository struct {
	db *gorm.DB
}

// NewTagRepository 创建标签数据访问实例
func NewTagRepository(db *gorm.DB) TagRepository {
	return &tagRepository{db: db}
}

// Create 创建标签
func (r *tagRepository) Create(tag *model.Tag) error {
	if tag == nil {
		return fmt.Errorf("tag不能为空")
	}
	return r.db.Create(tag).Error
}

// GetByID 根据ID获取标签
func (r *tagRepository) GetByID(id int64) (*model.Tag, error) {
	var tag model.Tag
	err := r.db.First(&tag, id).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("标签不存在: id=%d", id)
		}
		return nil, fmt.Errorf("查询标签失败: %w", err)
	}
	return &tag, nil
}

// GetByName 根据名称获取标签
func (r *tagRepository) GetByName(name string) (*model.Tag, error) {
	var tag model.Tag
	err := r.db.Where("name = ?", name).First(&tag).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil // 不存在返回nil,不报错
		}
		return nil, fmt.Errorf("查询标签失败: %w", err)
	}
	return &tag, nil
}

// GetOrCreate 获取或创建标签
func (r *tagRepository) GetOrCreate(name string) (*model.Tag, error) {
	if name == "" {
		return nil, fmt.Errorf("标签名称不能为空")
	}
	
	// 先查询
	tag, err := r.GetByName(name)
	if err != nil {
		return nil, err
	}
	
	// 如果存在,直接返回
	if tag != nil {
		return tag, nil
	}
	
	// 不存在,创建新标签
	tag = &model.Tag{
		Name:  name,
		Color: "#1890ff", // 默认蓝色
	}
	if err := r.Create(tag); err != nil {
		return nil, err
	}
	
	return tag, nil
}

// List 获取所有标签
func (r *tagRepository) List() ([]*model.Tag, error) {
	var tags []*model.Tag
	err := r.db.Order("article_count DESC, created_at DESC").Find(&tags).Error
	if err != nil {
		return nil, fmt.Errorf("查询标签列表失败: %w", err)
	}
	return tags, nil
}

// ListByArticle 获取文章的所有标签
func (r *tagRepository) ListByArticle(articleID int64) ([]*model.Tag, error) {
	var tags []*model.Tag
	err := r.db.Joins("JOIN article_tags ON article_tags.tag_id = tags.id").
		Where("article_tags.article_id = ?", articleID).
		Find(&tags).Error
	
	if err != nil {
		return nil, fmt.Errorf("查询文章标签失败: %w", err)
	}
	return tags, nil
}

// Update 更新标签
func (r *tagRepository) Update(tag *model.Tag) error {
	if tag == nil {
		return fmt.Errorf("tag不能为空")
	}
	if tag.ID == 0 {
		return fmt.Errorf("tag ID不能为0")
	}
	return r.db.Save(tag).Error
}

// Delete 删除标签
func (r *tagRepository) Delete(id int64) error {
	result := r.db.Delete(&model.Tag{}, id)
	if result.Error != nil {
		return fmt.Errorf("删除标签失败: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return fmt.Errorf("标签不存在: id=%d", id)
	}
	return nil
}

// AddToArticle 为文章添加标签
func (r *tagRepository) AddToArticle(articleID int64, tagID int64) error {
	// 检查关联是否已存在
	var count int64
	r.db.Model(&model.ArticleTag{}).
		Where("article_id = ? AND tag_id = ?", articleID, tagID).
		Count(&count)
	
	if count > 0 {
		return nil // 已存在,不重复添加
	}
	
	// 创建关联
	articleTag := &model.ArticleTag{
		ArticleID: articleID,
		TagID:     tagID,
	}
	
	if err := r.db.Create(articleTag).Error; err != nil {
		return fmt.Errorf("添加文章标签失败: %w", err)
	}
	
	// 更新标签的文章计数
	r.db.Model(&model.Tag{}).
		Where("id = ?", tagID).
		UpdateColumn("article_count", gorm.Expr("article_count + 1"))
	
	return nil
}

// RemoveFromArticle 从文章移除标签
func (r *tagRepository) RemoveFromArticle(articleID int64, tagID int64) error {
	result := r.db.Where("article_id = ? AND tag_id = ?", articleID, tagID).
		Delete(&model.ArticleTag{})
	
	if result.Error != nil {
		return fmt.Errorf("移除文章标签失败: %w", result.Error)
	}
	
	if result.RowsAffected > 0 {
		// 更新标签的文章计数
		r.db.Model(&model.Tag{}).
			Where("id = ?", tagID).
			UpdateColumn("article_count", gorm.Expr("article_count - 1"))
	}
	
	return nil
}

// SyncArticleTags 同步文章的标签
func (r *tagRepository) SyncArticleTags(articleID int64, tagNames []string) error {
	return r.db.Transaction(func(tx *gorm.DB) error {
		// 1. 删除旧标签关联
		if err := tx.Where("article_id = ?", articleID).Delete(&model.ArticleTag{}).Error; err != nil {
			return fmt.Errorf("删除旧标签失败: %w", err)
		}
		
		// 2. 添加新标签
		for _, tagName := range tagNames {
			if tagName == "" {
				continue
			}
			
			// 获取或创建标签
			tag, err := r.GetOrCreate(tagName)
			if err != nil {
				return err
			}
			
			// 创建关联
			articleTag := &model.ArticleTag{
				ArticleID: articleID,
				TagID:     tag.ID,
			}
			if err := tx.Create(articleTag).Error; err != nil {
				return fmt.Errorf("添加标签失败: %w", err)
			}
		}
		
		// 3. 重新计算所有标签的文章计数
		if err := r.recalculateAllTagCounts(tx); err != nil {
			return err
		}
		
		return nil
	})
}

// recalculateAllTagCounts 重新计算所有标签的文章计数
func (r *tagRepository) recalculateAllTagCounts(tx *gorm.DB) error {
	// 执行 SQL:
	// UPDATE tags SET article_count = (
	//     SELECT COUNT(*) FROM article_tags WHERE article_tags.tag_id = tags.id
	// )
	return tx.Exec(`
		UPDATE tags 
		SET article_count = (
			SELECT COUNT(*) 
			FROM article_tags 
			WHERE article_tags.tag_id = tags.id
		)
	`).Error
}

// Count 统计标签数量
func (r *tagRepository) Count() (int64, error) {
	var count int64
	err := r.db.Model(&model.Tag{}).Count(&count).Error
	if err != nil {
		return 0, fmt.Errorf("统计标签数量失败: %w", err)
	}
	return count, nil
}
